package com.im.interceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.im.service.common.smo.ICommonSMO;
import com.im.service.dto.FuncMenu;
import com.im.service.dto.Staff;
import net.sf.json.JSONObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.im.MDA;
import com.im.service.user.smo.IUserQuerySMO;


/**
 * 安全适配器，用于判断登录状态、权限控制等
 * @author yangwc
 *
 */
@Component
public class SecurityInterceptor extends HandlerInterceptorAdapter {
	
	private static final Logger logger = LogManager.getLogger(SecurityInterceptor.class);
	
	@Autowired
	private IUserQuerySMO userQuerySMO;
	@Autowired
	private ICommonSMO commonSMO;

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		super.afterCompletion(request, response, handler, ex);
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		super.postHandle(request, response, handler, modelAndView);
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		if("N".equals(MDA.SWITCH_CHECK_SESSION)){
			logger.debug("==SecurityInterceptor switch check session is close .");
			return true;		
		}
		//1.如果是可以公共权限访问的，直接放过
		String url = request.getRequestURI();
		url = url.replace("///", "/");
		url = url.replace("//", "/");
		for(String urlStr : MDA.URL_LIST_FOR_PUBLIC){
			if(url.indexOf(urlStr) >= 0 && urlStr.equals(url.substring(url.indexOf(urlStr) , url.length()))){
				return true;
			}
		}

		//重置标识,看是否为菜单权限
		boolean urlExistFlag =  false;
		//2.0需要校验权限编码
		for(String urlStr : MDA.URL_LIST_FOR_PERMISSION){
			if(url.indexOf(urlStr) >= 0 && urlStr.equals(url.substring(url.indexOf(urlStr) , url.length()))){
				urlExistFlag = true;
				break;
			}
		}

		logger.debug("==SecurityInterceptor check session. url is: " + url);
		JSONObject retJson = new JSONObject();
		//2.其余的必须登录后才可以操作
		Object seesionObj = request.getSession().getAttribute(MDA.SEESION_KEY);
		if(seesionObj == null){
			//sessionObj为空,那么跳转到登录
			if(urlExistFlag){
				//如果是菜单，返回登录
				response.sendRedirect(request.getContextPath() + "/loginController/login");
			}else{
				//服务接口，返回提示信息
				sendMsg(response,retJson.element("resultCode","-9999").element("resultMsg","检测到你当前未登录或者登录失效，请刷新界面重新登录!"));
			}
			return false;
		}
		Staff loginedStaff = (Staff) seesionObj;
		//判断是否账号是否有多次异地登录，保留最后一次会话
		if("Y".equals(MDA.SWITCH_LOGIN_ONCE_SAME_TIME)){
			Object sessionId = commonSMO.getValueFromRedis("SEESION_ID_"+loginedStaff.getStaffId());
			if(sessionId == null  || !sessionId.toString().equals(request.getSession().getId())){
				//非正常会话
				if(urlExistFlag){
					//如果是菜单，返回登录
					response.sendRedirect(request.getContextPath() + "/loginController/login?flag=loginOtherIp");
				}else{
					//服务接口，返回提示信息
					sendMsg(response,retJson.element("resultCode","-9999").element("resultMsg","检测到你账号在其他地方登录，请刷新界面重新登录!"));
				}
				return false;
			}
		}

		//====================================二、校验url权限
		if(urlExistFlag){
				
			//判断是否有权限校验权限
			boolean ifHashPermission = checkPermission(request, loginedStaff.getStaffId());

			//2.0是否有权限
			if(ifHashPermission){
				return super.preHandle(request, response, handler);
			}else{
				//跳转到无权限
				response.sendRedirect(request.getContextPath() + "/loginController/noPermisssion");
				return false;
			}
		}
		
		return true;
		
	}


	private boolean checkPermission(HttpServletRequest request,String staffId){
		boolean hasPermission = false;
		
		//1.0 session是否有权限列表,无则查询数据库，同时存入session
		Object object = request.getSession().getAttribute("Permission_"+staffId);
		
		List<String> permissionList = null;
		if(object == null){
			
			permissionList = new ArrayList<>();

			Map<String,Object> param = new HashMap<>();
			param.put("staffId",staffId);
			List<FuncMenu> modulars = userQuerySMO.queryStaffFuncMenus(param);

			if(modulars != null && modulars.size() > 0){
				for(FuncMenu modular :  modulars){
					if(modular.getUrl() != null && !"".equals(modular.getUrl().trim())){
						permissionList.add(modular.getUrl());
					}

					if(modular.getChildMenu() != null){
						for(FuncMenu subModular : modular.getChildMenu()){
							if(subModular.getUrl() != null && !"".equals(subModular.getUrl().trim())){
								permissionList.add(subModular.getUrl());
							}
						}
					}
				}
			}
			//首页是默认都有权限
			permissionList.add("userController/index");
			//放入session
			request.getSession().setAttribute("Permission_"+staffId, permissionList);
			
		}else{
			 permissionList = (List<String>) object;
		}
		
		String url = request.getRequestURI();
		url = url.replace("///", "/");
		url = url.replace("//", "/");
		//判断权限
		for(String per : permissionList){
			if(url.indexOf(per) >= 0  && per.equals(url.substring(url.indexOf(per), url.length()))){
				hasPermission = true;
				break;
			}
			
		}
		return hasPermission;
	}

	private String getUserRoleStr(String url){
		String userRoleStr = "";
//		for(String urlStr : MDA.URL_LIST_TO_USER_ROLE_STAFF){
//			if(url.indexOf(urlStr) >= 0 && urlStr.equals(url.substring(url.indexOf(urlStr) , url.length()))){
//				userRoleStr = "?userRole=staff";
//				break;
//			}
//		}
		return userRoleStr;
	}

	private void sendMsg(HttpServletResponse response, JSONObject jsonObject){

		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json; charset=utf-8");
		PrintWriter out = null;
		try {
			out = response.getWriter();
			out.append(jsonObject.toString());
			logger.debug("返回是\n");
			logger.debug(jsonObject);
		} catch (Exception e) {
			logger.error("SecurityInterceptor 执行session判断时异常：\n",e);
		} finally {
			if (out != null) {
				out.close();
			}
		}
	}


}
